package com.auth.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.marry.core.constants.JWTConstants;
import com.marry.core.constants.RedisConstants;
import com.marry.core.exception.BusinessException;
import com.marry.core.utils.JWTUtiles;
import com.marry.core.utils.Md5Utils;
import com.auth.domain.AuthUser;
import com.auth.repository.MyUserDetailsService;
import com.nimbusds.jose.JOSEException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @program: webfluxT
 * @description: as
 * @author: 杨超
 * @create: 2021-06-18 16:02
 **/
@Api(value = "授权中心", tags = {"授权中心的接口"})
@RestController
public class AuthController {

    @Resource
    MyUserDetailsService myUserDetailsService;

    @Resource
    PasswordEncoder passwordEncoder;

    @Resource
    ReactiveAuthenticationManager authenticationManager;

    @Resource
    private RedisTemplate<String, Object> template;

    @Resource
    private StringRedisTemplate stringRedisTemplate;


    @ApiOperation(value = "登录接口", notes = "")
    @PostMapping("/login")
    public Mono<AuthUser> login(@RequestParam(value = "userName") String userName, @RequestParam(value = "password") String password) {
        //密码验证
        Mono<Authentication> authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName, password));
        //开始赋值
        return authentication.map(auth ->{
            AuthUser authUser = (AuthUser) auth.getPrincipal();
            String s = JSON.toJSONString(authUser);
            String token = null;
            try {
                token = JWTUtiles.createToken(s);
            } catch (JOSEException e) {
                e.printStackTrace();
            }
            authUser.setToken(token);

            // 生成Key， 把权限放入到redis中
            String keyPrefix = RedisConstants.TOKEN_KEY_PREFIX + authUser.getId() + ":";
            String keySuffix = Md5Utils.getMD5(token.getBytes());
            String key = keyPrefix + keySuffix;
            String authKey = key + RedisConstants.AUTH_KEY;

            stringRedisTemplate.opsForValue().set(authKey, JSONObject.toJSONString(authUser.getAuthorities()), JWTConstants.EXPIRE_TIME, TimeUnit.SECONDS);
            Object o = stringRedisTemplate.opsForValue().get(authKey);
            return authUser;
        }).onErrorResume(e ->{
            e.printStackTrace();
            BusinessException exception = null;
            String localizedMessage = e.getLocalizedMessage();
            if("Invalid Credentials".equals(localizedMessage)){
                 exception = new BusinessException(500, "密码错误");
            }
            return Mono.error(exception);
        });


    }

    @ApiOperation(value = "测试接口", notes = "")
    @RequestMapping(value = "/test",method = RequestMethod.POST)
    public Mono<String> test(@RequestParam("testData")String testData){
       return   Mono.just(testData);
    }

    @RequestMapping(value = "/test2",method = RequestMethod.POST)
    public Flux<String> test2(){
        Flux.just(new String[]{"hello",",","nihao","!"}).subscribe(System.out::println);
        return Flux.just(new String[]{"hello",",","nihao","!"});
    }


}
